<?php

namespace App\Http\Controllers\Freelancer;

use App\Http\Controllers\Controller;
use App\Models\Freelancer;
use App\Models\FreelancerFourElementLog;
use App\Services\FourElement\FourElementVerifier;
use App\Services\FaceRecognition\FaceRecognitionVerifierManager;
use App\Services\IdentityOcr\IdentityOcrResult;
use App\Services\IdentityOcr\IdentityOcrVerifierManager;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Validator;
use RuntimeException;

class ProfileController extends Controller
{
    protected FourElementVerifier $fourElementVerifier;
    protected IdentityOcrVerifierManager $identityOcrManager;
    protected FaceRecognitionVerifierManager $faceRecognitionManager;

    public function __construct(
        FourElementVerifier $fourElementVerifier,
        IdentityOcrVerifierManager $identityOcrManager,
        FaceRecognitionVerifierManager $faceRecognitionManager
    ) {
        $this->fourElementVerifier = $fourElementVerifier;
        $this->identityOcrManager = $identityOcrManager;
        $this->faceRecognitionManager = $faceRecognitionManager;
    }

    /**
     * 获取用户资料
     */
    public function show(Request $request)
    {
        $user = $request->user();

        return response()->json([
            'code' => 0,
            'message' => '获取成功',
            'data' => [
                'phone' => $user->phone,
                'name' => $user->name,
                'avatar' => $user->avatar ?? '',
                'real_name' => $user->real_name ?? '',
                'id_card' => $user->id_card ?? '',
                'address' => $user->address ?? '',
                'bank_account' => $user->bank_account ?? '',
                'gender' => $user->gender ?? '',
                'birth_date' => $user->birth_date ?? '',
                'status' => $user->status,
                'verification_status' => $user->verification_status ?? Freelancer::VERIFICATION_PENDING,
                'id_card_recognition_status' => $user->id_card_recognition_status ?? Freelancer::RECOGNITION_PENDING,
                'face_recognition_status' => $user->face_recognition_status ?? Freelancer::RECOGNITION_PENDING,
                'created_at' => $user->created_at->format('Y-m-d H:i:s'),
            ]
        ]);
    }

    /**
     * 更新用户资料
     */
    public function update(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'name' => 'sometimes|string|max:50',
            'real_name' => 'sometimes|string|max:50',
            'id_card' => 'sometimes|string|size:18',
            'address' => 'sometimes|string|max:200',
            'gender' => 'sometimes|in:male,female',
            'birth_date' => 'sometimes|date',
        ]);

        if ($validator->fails()) {
            return response()->json([
                'code' => 1,
                'message' => '参数验证失败',
                'data' => $validator->errors()
            ]);
        }

        try {
            $user = $request->user();
            $updateData = $request->only([
                'name', 'real_name', 'id_card', 'address', 'gender', 'birth_date'
            ]);

            $user->update($updateData);

            return response()->json([
                'code' => 0,
                'message' => '更新成功',
                'data' => [
                    'phone' => $user->phone,
                    'name' => $user->name,
                    'avatar' => $user->avatar ?? '',
                    'real_name' => $user->real_name ?? '',
                    'id_card' => $user->id_card ?? '',
                    'address' => $user->address ?? '',
                    'bank_account' => $user->bank_account ?? '',
                    'gender' => $user->gender ?? '',
                    'birth_date' => $user->birth_date ?? '',
                    'status' => $user->status,
                    'verification_status' => $user->verification_status ?? Freelancer::VERIFICATION_PENDING,
                    'id_card_recognition_status' => $user->id_card_recognition_status ?? Freelancer::RECOGNITION_PENDING,
                    'face_recognition_status' => $user->face_recognition_status ?? Freelancer::RECOGNITION_PENDING,
                ]
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'code' => 1,
                'message' => '更新失败，请稍后重试',
                'data' => null
            ]);
        }
    }

    /**
     * 实名认证（四要素核验）
     */
    public function realNameVerify(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'phone' => 'required|string|max:50',
            'name' => 'required|string|max:50',
            'idCard' => 'required|string|size:18',
            'bankCard' => 'required|string|max:30',
        ]);

        if ($validator->fails()) {
            return response()->json([
                'code' => 1,
                'message' => '参数验证失败',
                'data' => $validator->errors(),
            ]);
        }

        $user = $request->user();

        $inputPhone = $request->input('phone');
        $userPhone = $user->phone;
        $phone = empty($userPhone) ? trim($inputPhone) : $userPhone;
        $name = $request->input('name');
        $idCard = $request->input('idCard');
        $bankCard = $request->input('bankCard');

        $payload = [
            'name' => $name,
            'phone' => $phone,
            'id_card' => $idCard,
            'bank_account' => $bankCard,
        ];

        $logEntry = null;

        try {
            $user->fill([
                'name' => $name,
                'phone' => $phone,
                'id_card' => $idCard,
                'bank_account' => $bankCard,
            ]);

            $user->verification_status = Freelancer::VERIFICATION_PENDING;
            $user->save();

            $logEntry = FreelancerFourElementLog::create([
                'freelancer_id' => $user->id,
                'request_payload' => $payload,
                'response_payload' => null,
                'status' => 'processing',
                'message' => null,
            ]);

            $result = $this->fourElementVerifier->verify($name, $phone, $idCard, $bankCard);

            if ($result->passed) {
                $user->verification_status = Freelancer::VERIFICATION_APPROVED;
                $status = 'passed';
            } else {
                $user->verification_status = Freelancer::VERIFICATION_REJECTED;
                $status = 'failed';
            }

            $user->save();

            if ($logEntry) {
                $logEntry->update([
                    'status' => $status,
                    'message' => $result->message,
                    'response_payload' => [
                        'passed' => $result->passed,
                        'message' => $result->message,
                        'code' => $result->code,
                        'context' => $result->context,
                    ],
                ]);
            }

            return response()->json([
                'code' => $result->passed ? 0 : 1,
                'message' => $result->message ?? ($result->passed ? '实名认证成功' : '实名认证失败'),
                'data' => [
                    'verification_status' => $user->verification_status,
                    'user' => $this->formatUserData($user->fresh()),
                ],
            ]);
        } catch (\Throwable $e) {
            Log::error('[Freelancer] Real name verification failed', [
                'freelancer_id' => $user->id,
                'error' => $e->getMessage(),
                'file' => $e->getFile(),
                'line' => $e->getLine(),
            ]);

            if ($logEntry) {
                $logEntry->update([
                    'status' => 'error',
                    'message' => $e->getMessage(),
                    'response_payload' => [
                        'exception' => [
                            'message' => $e->getMessage(),
                            'file' => $e->getFile(),
                            'line' => $e->getLine(),
                        ],
                    ],
                ]);
            }

            $user->verification_status = Freelancer::VERIFICATION_REJECTED;
            $user->save();

            return response()->json([
                'code' => 1,
                'message' => '实名认证失败：' . $e->getMessage(),
                'data' => null,
            ]);
        }
    }

    /**
     * 身份证识别
     */
    public function idCardOcr(Request $request)
    {
        $user = $request->user();
        $validator = Validator::make($request->all(), [
            'frontImage' => 'required|string',
            'backImage' => 'required|string',
        ]);

        if ($validator->fails()) {
            return response()->json([
                'code' => 1,
                'message' => '参数验证失败',
                'data' => $validator->errors(),
            ]);
        }

        $frontTemp = $backTemp = null;
        $uploadedFrontPath = $uploadedBackPath = null;

        try {
            $frontTemp = $this->storeBase64Image($request->input('frontImage'));
            $backTemp = $this->storeBase64Image($request->input('backImage'));

            [$uploadedFrontPath, $uploadedBackPath] = $this->uploadIdCardImagesToS3($user, $frontTemp, $backTemp);
        } catch (\Throwable $e) {
            $this->cleanupTempFiles([$frontTemp, $backTemp]);
            return response()->json([
                'code' => 1,
                'message' => '身份证图片处理失败: ' . $e->getMessage(),
                'data' => null,
            ]);
        }

        $verifier = $this->identityOcrManager->driver();

        $ocrResult = $verifier->recognizeWithIdentity(
            $user->real_name ?? $user->name ?? '',
            $user->id_card ?? '',
            $frontTemp['path'],
            $backTemp['path']
        );

        $this->cleanupTempFiles([$frontTemp, $backTemp]);

        $user->id_card_recognition_status = $ocrResult->success
            ? Freelancer::RECOGNITION_APPROVED
            : Freelancer::RECOGNITION_REJECTED;
        $user->save();

        $message = $ocrResult->message ?: ($ocrResult->success ? '身份证上传成功' : '身份证上传失败');
        $code = $ocrResult->success ? 0 : 1;

        return response()->json([
            'code' => $code,
            'message' => $message,
            'data' => [
                's3' => [
                    'front' => $uploadedFrontPath,
                    'back' => $uploadedBackPath,
                ],
            ],
        ]);
    }

    /**
     * 人脸识别（H5）
     */
    public function faceRecognition(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'returnUrl' => 'required|url',
        ]);

        if ($validator->fails()) {
            return response()->json([
                'code' => 1,
                'message' => '参数验证失败',
                'data' => $validator->errors(),
            ]);
        }

        $user = $request->user();

        if (empty($user->id_card)) {
            return response()->json([
                'code' => 1,
                'message' => '请先完成身份证明信息后再发起人脸核验',
                'data' => null,
            ]);
        }

        $params = [
            'orderNo' => (string) $user->id,
            'name' => $user->real_name ?? $user->name ?? '',
            'identityCard' => $user->id_card,
            'backUrl' => $request->input('returnUrl'),
            'notifyUrl' => route('face-recognition.notify', [], true),
            'startFrom' => 1, // 启动方式1=browser ：表示在浏览器启动刷脸,2=app ：表示在 app 里启动刷脸,默认值为browser
        ];

        $driver = $this->faceRecognitionManager->driver();
        $result = $driver->start($params);

        $user->face_recognition_status = Freelancer::RECOGNITION_PENDING;
        $user->save();

        if ($result->success) {
            return response()->json([
                'code' => 0,
                'message' => $result->message ?? '人脸核验链接获取成功',
                'data' => [
                    'orderNo' => $result->data['orderNo'] ?? $params['orderNo'],
                    'startFaceUrl' => $result->data['url'] ?? $result->data['startFaceUrl'] ?? '',
                    'expireTime' => $result->data['expireTime'] ?? null,
                ],
            ]);
        }

        $user->face_recognition_status = Freelancer::RECOGNITION_REJECTED;
        $user->save();

        return response()->json([
            'code' => 1,
            'message' => $result->message ?? '人脸核验失败',
            'data' => [
                'code' => $result->code,
                'context' => $result->context,
            ],
        ]);
    }

    private function formatUserData(Freelancer $user): array
    {
        return [
            'phone' => $user->phone,
            'name' => $user->name,
            'avatar' => $user->avatar ?? '',
            'real_name' => $user->real_name ?? '',
            'id_card' => $user->id_card ?? '',
            'address' => $user->address ?? '',
            'bank_account' => $user->bank_account ?? '',
            'gender' => $user->gender ?? '',
            'birth_date' => $user->birth_date ?? '',
            'status' => $user->status,
            'verification_status' => $user->verification_status ?? Freelancer::VERIFICATION_PENDING,
            'id_card_recognition_status' => $user->id_card_recognition_status ?? Freelancer::RECOGNITION_PENDING,
            'face_recognition_status' => $user->face_recognition_status ?? Freelancer::RECOGNITION_PENDING,
            'created_at' => optional($user->created_at)->format('Y-m-d H:i:s'),
        ];
    }

    private function storeBase64Image(string $base64): array
    {
        $meta = null;
        if (str_contains($base64, ',')) {
            [$meta, $base64] = explode(',', $base64, 2);
        }

        $binary = base64_decode($base64, true);
        if ($binary === false) {
            throw new RuntimeException('图片Base64解码失败');
        }

        $mime = null;
        $extension = 'jpg';
        if ($meta && preg_match('/data:(.*?);base64/', $meta, $matches)) {
            $mime = $matches[1] ?? null;
            $extension = $this->guessExtensionFromMime($mime);
        }

        $tempPath = tempnam(sys_get_temp_dir(), 'ocr_');
        file_put_contents($tempPath, $binary);

        return [
            'path' => $tempPath,
            'extension' => $extension,
            'mime' => $mime,
        ];
    }

    private function cleanupTempFiles(array $paths): void
    {
        foreach ($paths as $path) {
            if (is_array($path)) {
                $path = $path['path'] ?? null;
            }
            if ($path && file_exists($path)) {
                @unlink($path);
            }
        }
    }

    private function guessExtensionFromMime(?string $mime): string
    {
        return match ($mime) {
            'image/jpeg', 'image/jpg' => 'jpg',
            'image/png' => 'png',
            'image/gif' => 'gif',
            'image/webp' => 'webp',
            'image/bmp' => 'bmp',
            'image/heic' => 'heic',
            'image/heif' => 'heif',
            'image/tiff', 'image/tif' => 'tiff',
            default => 'jpg',
        };
    }

    private function uploadIdCardImagesToS3(Freelancer $user, array $frontTemp, array $backTemp): array
    {
        $disk = Storage::disk();
        $timestamp = now()->format('YmdHis');
        $directory = "freelancers/{$user->id}/";

        $frontFilename = 'idFront_' . $timestamp . '.' . ($frontTemp['extension'] ?? 'jpg');
        $backFilename = 'idBack_' . $timestamp . '.' . ($backTemp['extension'] ?? 'jpg');

        try {
            $disk->put($directory . $frontFilename, file_get_contents($frontTemp['path']));
            $disk->put($directory . $backFilename, file_get_contents($backTemp['path']));
        } catch (\Throwable $e) {
            throw new RuntimeException('身份证图片上传失败: ' . $e->getMessage(), previous: $e);
        }

        return [
            $directory . $frontFilename,
            $directory . $backFilename,
        ];
    }

    private function formatOcrResponse(IdentityOcrResult $result): array
    {
        return [
            'success' => $result->success,
            'message' => $result->message,
            'code' => $result->code,
            'data' => $result->data,
            'context' => $result->context,
        ];
    }
}
